package dms.repository.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;

import dms.model.Building;
import dms.model.Campus;
import dms.model.Dormitory;
import dms.model.util.FindUtil;
import dms.model.util.PageIterator;
import dms.repository.DormitoryRepository;
import dms.util.HibernateUtil;

/**
 * 
 * @author 李健
 *
 */
public class DormitoryRepositoryHibernate implements DormitoryRepository {

	@Override
	public Dormitory createDormitory(Dormitory dormitoryInfo) {
		Session session = null;
		Transaction tx = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			session.save(dormitoryInfo);
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				session.close();
			}
		}
		return dormitoryInfo;
	}

	@Override
	public void deleteById(Long id) {
		Session session = null;
		Transaction tx = null;
		Dormitory dormitory = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			dormitory = (Dormitory) session.load(Dormitory.class, id);
			session.delete(dormitory);
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				session.close();
			}
		}
		
	}

	@Override
	public PageIterator<Dormitory> findByBuilding(int start, int count, Building building) {
		Session session = null;
		Transaction tx = null;
		
		PageIterator<Dormitory> pageIter = null;
		List<Dormitory> list = null;
		Long allCount = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			String countQuery = "select count(*) from Dormitory d where d.building = ? ";
			String findQuery = "select d from Dormitory d where d.building = ?";
			Collection params = new ArrayList();
			params.add(building);
			
			allCount = FindUtil.calculateAllCount(session, countQuery, params);
			list = FindUtil.getEntitiesByPage(session, findQuery, params, start, count);
			pageIter = new PageIterator<Dormitory>(list, allCount, start, count);
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				session.close();
			}
		}
		
		return pageIter;
	}

	@Override
	public Dormitory findByBuildingAndName(Building building, String name) {
		Session session = null;
		Transaction tx = null;
		Dormitory dormitory = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			Query query = session.createQuery("select d from Dormitory d where d.building = :building " +
											  "and d.name = :name");
			query.setParameter("building", building)
			     .setParameter("name", name);
			dormitory = (Dormitory) query.uniqueResult();
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				session.close();
			}
		}
		return dormitory;
		
	}

	@Override
	public Dormitory findById(Long id) {
		Session session = null;
		Transaction tx = null;
		Dormitory dormitory = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			dormitory = (Dormitory) session.get(Dormitory.class, id);
			//initialize dormitory property
			Hibernate.initialize(dormitory);
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				session.close();
			}
		}
		
		return dormitory;
	}

	@Override
	public Dormitory updateDormitory(Dormitory dormitoryInfo) {
		Session session = null;
		Transaction tx = null;
		Dormitory dormitory = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			dormitory = (Dormitory) session.merge(dormitoryInfo);
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				session.close();
			}
		}
		
		return dormitory;
	}

	@Override
	public void deleteDormitories(List<Long> ids) {
		Session session = null;
		Transaction tx = null;
		
		String deleteQuery = "delete from Dormitory d where d.id in (:ids)";
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			session.createQuery(deleteQuery)
				   .setParameterList("ids", ids)
				   .executeUpdate();
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		
	}

	@Override
	public PageIterator<Dormitory> findAll(int start, int count) {
		Session session = null;
		Transaction tx = null;
		
		PageIterator<Dormitory> pageIter = null;
		List<Dormitory> list = null;
		Long allCount = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			String countQuery = "select count(*) from Dormitory d ";
			String findQuery = "select d from Dormitory d ";
			
			allCount = FindUtil.calculateAllCount(session, countQuery, null);
			list = FindUtil.getEntitiesByPage(session, findQuery, null, start, count);
			pageIter = new PageIterator<Dormitory>(list, allCount, start, count);
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		
		return pageIter;
	}

	@Override
	public PageIterator<Dormitory> findByCampus(int start, int count, Campus campus) {
		Session session = null;
		Transaction tx = null;
		
		PageIterator<Dormitory> pageIter = null;
		List<Dormitory> list = null;
		Long allCount = null;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			String countQuery = "select count(*) from Dormitory d where d.building.campus = ? ";
			String findQuery = "select d from Dormitory d where d.building.campus = ?";
			Collection params = new ArrayList();
			params.add(campus);
			
			allCount = FindUtil.calculateAllCount(session, countQuery, params);
			list = FindUtil.getEntitiesByPage(session, findQuery, params, start, count);
			pageIter = new PageIterator<Dormitory>(list, allCount, start, count);
			
			tx.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		
		return pageIter;
	}

	
}
